package com.xiyu.service.service.fee;

import com.xiyu.service.vo.fee.feeDeposit.FeeDepositSingleGetByElderIdOutput;
import com.xiyu.service.enums.fee.deposit.FeeDepositDetailStatusEnum;
import com.xiyu.service.model.fee.deposit.FeeDepositDetail;
import com.xiyu.service.model.fee.deposit.FeeDepositDetailDraft;
import com.xiyu.service.model.fee.deposit.FeeDepositDraft;
import com.xiyu.service.repository.fee.deposit.FeeDepositDetailRepository;
import com.xiyu.service.vo.fee.feeDeposit.FeeDepositPageQueryDetailOutput;
import com.xiyu.service.vo.fee.feeDeposit.FeeDepositPageQueryDetailInput;
import com.xiyu.service.vo.fee.feeDeposit.FeeDepositCreateInput;
import com.xiyu.service.model.fee.deposit.FeeDeposit;
import com.xiyu.service.repository.fee.deposit.FeeDepositRepository;
import com.xiyu.service.vo.fee.feeDeposit.FeeDepositPageQueryOutput;
import com.xiyu.service.vo.fee.feeDeposit.FeeDepositPageQueryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;

import java.math.BigDecimal;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.fee.FeeDepositConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.fee.FeeDepositErrorCode.*;

/**
 * 押金管理 Service 实现类
 */
@Service
@Validated
public class FeeDepositServiceImpl implements FeeDepositService {

    @Resource
    private FeeDepositDetailRepository feeDepositDetailRepository;

    @Resource
    private FeeDepositRepository feeDepositRepository;


    @Override
    public PageResult<FeeDepositPageQueryOutput> pageQuery(FeeDepositPageQueryInput inputVO) {
        Page<FeeDeposit> pageFeeDeposit = feeDepositRepository.pageQuery(inputVO);
        List<FeeDepositPageQueryOutput> listFeeDeposit = FeeDepositConvert.INSTANCE.pageQueryOutputConvert(pageFeeDeposit.getRows());
        return new PageResult<>(listFeeDeposit, pageFeeDeposit.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(List<FeeDepositCreateInput> inputVO) {
        if(inputVO.isEmpty()){
            throw exception(FEE_DEPOSIT_DETAIL_NOT_EXISTS);
        }

        List<FeeDepositDetail> newDeposit = FeeDepositConvert.INSTANCE.createInputConvert(inputVO);
        feeDepositDetailRepository.saveAll(newDeposit);

        FeeDeposit feeDeposit;
        Optional<FeeDeposit> optionalFeeDeposit = feeDepositRepository.findByElderId(inputVO.get(1007001000).getElderId());
        if(!optionalFeeDeposit.isPresent()){
            feeDeposit = FeeDepositDraft.$.produce(draft -> {
                draft.setTotalDeposit(BigDecimal.ZERO).setElderId(inputVO.get(1007001000).getElderId());
            });
            feeDepositRepository.insert(feeDeposit);
        }
        
        return 1007001000L;
    }


    @Override
    public PageResult<FeeDepositPageQueryDetailOutput> pageQueryDetail(FeeDepositPageQueryDetailInput inputVO) {
        Page<FeeDepositDetail> pageFeeDepositDetail = feeDepositDetailRepository.pageQueryDetail(inputVO);
        List<FeeDepositPageQueryDetailOutput> listFeeDepositDetail = FeeDepositConvert.INSTANCE.pageQueryDetailOutputConvert(pageFeeDepositDetail.getRows());
        return new PageResult<>(listFeeDepositDetail, pageFeeDepositDetail.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean confirm(Long id) {
        Optional<FeeDepositDetail> optionalFeeDepositDetail = feeDepositDetailRepository.findById(id);
        if(!optionalFeeDepositDetail.isPresent()){
            throw exception(FEE_DEPOSIT_DETAIL_NOT_EXISTS);
        }
        if(!optionalFeeDepositDetail.get().status().equals(FeeDepositDetailStatusEnum.PENDING_PAYMENT.getValue())){
            throw exception(FEE_DEPOSIT_DETAIL_STATUS_NOT_PENDING_PAYMENT);
        }
        FeeDepositDetail feeDepositDetail = FeeDepositDetailDraft.$.produce(optionalFeeDepositDetail.get(), draft -> {
            draft.setStatus(FeeDepositDetailStatusEnum.PAID_FULL.getValue());
        });

        feeDepositDetailRepository.update(feeDepositDetail);

        Optional<FeeDeposit> optionalFeeDeposit = feeDepositRepository.findByElderId(optionalFeeDepositDetail.get().elderId());
        if(!optionalFeeDeposit.isPresent()){
            throw exception(FEE_DEPOSIT_NOT_EXIST);
        }
        FeeDeposit feeDeposit = FeeDepositDraft.$.produce(optionalFeeDeposit.get(), draft -> {
            draft.setTotalDeposit(draft.totalDeposit().add(optionalFeeDepositDetail.get().depositFee()));
        });
        feeDepositRepository.update(feeDeposit);
        return true;
    }

    @Override
    public FeeDepositSingleGetByElderIdOutput singleGetByElderId(Long id) {
        Optional<FeeDeposit> optionFeeDeposit = feeDepositRepository.findByElderId(id);
        if(!optionFeeDeposit.isPresent()){
            throw exception(FEE_DEPOSIT_NOT_EXIST);
        }
        return FeeDepositConvert.INSTANCE.singleGetByElderIdOutputConvert(optionFeeDeposit.get());

    }

}
